package com.gitee.alpha.ie.convert.data;

import com.gitee.alpha.ie.ExcelField;
import com.gitee.alpha.ie.RowWrapper;
import com.gitee.alpha.ie.SimpleReadContext;
import com.gitee.alpha.ie.convert.CellDataConverter;
import com.gitee.alpha.ie.convert.CellValueConverter;
import com.gitee.alpha.ie.convert.SimpleCellValueConverter;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellData;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * 多表头类型数据转换<br>
 *
 * @author 冰羽
 * @version 2.2.0
 */
@Slf4j
public class ManyTableDataConverter implements CellDataConverter {

  private List<Integer> rowIndexes;
  private SimpleReadContext readContext;
  @Getter private CellValueConverter cellValueConverter;

  public ManyTableDataConverter(Set<Integer> rowIndexes, SimpleReadContext readContext) {
    this(rowIndexes, readContext, new SimpleCellValueConverter());
  }

  public ManyTableDataConverter(
      Set<Integer> rowIndexes,
      SimpleReadContext readContext,
      CellValueConverter cellValueConverter) {
    Set<Integer> set = new TreeSet<>(Comparator.naturalOrder());
    set.addAll(rowIndexes);
    this.rowIndexes = Lists.newArrayList(set);
    this.readContext = readContext;
    this.cellValueConverter = cellValueConverter;
  }

  @Override
  public RowWrapper convert(
      Map<Integer, List<ExcelField>> excelFields,
      Map<Integer, CellData> originHeader,
      Map<Integer, Object> data,
      AnalysisContext context) {
    RowWrapper wrapper = new RowWrapper();
    Map<String, Object> map = Maps.newHashMap();
    Integer rowIndex = context.readRowHolder().getRowIndex();
    int cellNotEmptyCount = 0;
    boolean isHeader = false;

    try {
      RowStatusVo vo = buildRowStatusVo(rowIndex, excelFields);
      isHeader = vo.isHeader();
      if (vo.isNotEmpty() && isHeader == false) {
        List<ExcelField> list = vo.getExcelFields();
        for (ExcelField excelField : list) {
          try {
            Object o = data.get(excelField.getCellIndex());
            // 值转换函数
            Object cellValue = getCellValueConverter().convert(o, excelField.getJavaType());
            if (cellValue != null) {
              map.put(excelField.getName(), cellValue);
            }
          } catch (Exception e) {
            log.warn("convert cell value exception, error: {}", e);
          }
        }

        wrapper.setExcelFields(list);
      }

      wrapper.setRowIndex(rowIndex);
      wrapper.setRowData(map);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    if (map.size() == 0) {
      wrapper.setRowData(null);
      // 可能多sheet中一个sheet中存在多个表头的情况，当获取到表头所在行的时候会进入此分支
      // 而表头不属于数据空行的范畴
      if (isHeader == false) {
        this.readContext.setStatusBlank(rowIndex, "数据空行");
      }
    }

    return wrapper;
  }

  private RowStatusVo buildRowStatusVo(
      Integer rowIndex, Map<Integer, List<ExcelField>> excelFields) {
    RowStatusVo vo = new RowStatusVo();

    if (CollectionUtil.isNotEmpty(rowIndexes)) {
      // 取得最后一个表头的行号，若行号大于了最后一个表头所在的行，则全部为最后一个表的数据
      Integer index = rowIndexes.get(rowIndexes.size() - 1);
      if (index.equals(rowIndex)) {
        vo.setHeader(true);
      } else if (rowIndex > index) {
        vo.setHeader(false);
      } else {
        for (int i = 0; i < rowIndexes.size(); i++) {
          index = rowIndexes.get(i);
          if (i == rowIndexes.size() - 1) {
            vo.setHeader(index != null && index.equals(rowIndex));
            break;
          } else {
            Integer nextIndex = rowIndexes.get(i + 1);
            if (index.equals(rowIndex) || nextIndex.equals(rowIndex)) {
              index = rowIndex;
              vo.setHeader(true);
              break;
            } else if (rowIndex > index && rowIndex < nextIndex) {
              vo.setHeader(false);
              break;
            }
          }
        }
      }

      vo.setExcelFields(excelFields.get(index));
    }

    return vo;
  }

  /**
   * 当前数据行的状态<br>
   *
   * @author 冰羽
   * @version 2.2.0
   */
  @Data
  private static class RowStatusVo {

    /** 当前表头 */
    private List<ExcelField> excelFields;
    /** 是否表头 */
    private boolean header = false;

    public boolean isNotEmpty() {
      return CollectionUtil.isNotEmpty(excelFields);
    }
  }
}
